﻿using System;
using System.Net.Security;
using System.ServiceModel;
using System.Text;
using System.Xml.Serialization;

namespace Nardax.ServiceModel.Discovery.Bindings
{
    [XmlRoot(BindingSerializer.RootElementName)]
    public class SerializableWSHttpBinding : SerializableBinding<WSHttpBinding>
    {
        public SerializableWSHttpBinding()
        {
            Binding = new WSHttpBinding();
        }

        public SerializableWSHttpBinding(WSHttpBinding binding)
        {
            Binding = binding;
        }

        [XmlAttribute("AC")]
        public bool AllowCookies
        {
            get { return Binding.AllowCookies; }
            set { Binding.AllowCookies = value; }
        }

        [XmlAttribute("BPOL")]
        public bool BypassProxyOnLocal
        {
            get { return Binding.BypassProxyOnLocal; }
            set { Binding.BypassProxyOnLocal = value; }
        }

        [XmlAttribute("HNCM")]
        public HostNameComparisonMode HostNameComparisonMode
        {
            get { return Binding.HostNameComparisonMode; }
            set { Binding.HostNameComparisonMode = value; }
        }

        [XmlAttribute("MBPS")]
        public long MaxBufferPoolSize
        {
            get { return Binding.MaxBufferPoolSize; }
            set { Binding.MaxBufferPoolSize = value; }
        }

        [XmlAttribute("MRMS")]
        public long MaxReceivedMessageSize
        {
            get { return Binding.MaxReceivedMessageSize; }
            set { Binding.MaxReceivedMessageSize = value; }
        }

        [XmlAttribute("ME")]
        public WSMessageEncoding MessageEncoding
        {
            get { return Binding.MessageEncoding; }
            set { Binding.MessageEncoding = value; }
        }

        [XmlAttribute("PA")]
        public string ProxyAddress
        {
            get { return Binding.ProxyAddress != null ? Binding.ProxyAddress.ToString() : null; }
            set { Binding.ProxyAddress = !String.IsNullOrWhiteSpace(value) ? new Uri(value) : null; }
        }

        [XmlAttribute("TE")]
        public string TextEncoding
        {
            get { return Binding.TextEncoding.WebName; }
            set
            {
                switch (value)
                {
                    case "utf-8":
                        Binding.TextEncoding = Encoding.UTF8;
                        break;

                    case "utf-16":
                        Binding.TextEncoding = Encoding.Unicode;
                        break;

                    case "utf-16BE":
                        Binding.TextEncoding = Encoding.BigEndianUnicode;
                        break;
                }
            }
        }

        [XmlAttribute("TF")]
        public bool TransactionFlow
        {
            get { return Binding.TransactionFlow; }
            set { Binding.TransactionFlow = value; }
        }

        [XmlAttribute("UDWP")]
        public bool UseDefaultWebProxy
        {
            get { return Binding.UseDefaultWebProxy; }
            set { Binding.UseDefaultWebProxy = value; }
        }

        [XmlAttribute("RQ-MAL")]
        public int MaxArrayLength
        {
            get { return Binding.ReaderQuotas.MaxArrayLength; }
            set { Binding.ReaderQuotas.MaxArrayLength = value; }
        }

        [XmlAttribute("RQ-MBPR")]
        public int MaxBytesPerRead
        {
            get { return Binding.ReaderQuotas.MaxBytesPerRead; }
            set { Binding.ReaderQuotas.MaxBytesPerRead = value; }
        }

        [XmlAttribute("RQ-MD")]
        public int MaxDepth
        {
            get { return Binding.ReaderQuotas.MaxDepth; }
            set { Binding.ReaderQuotas.MaxDepth = value; }
        }

        [XmlAttribute("RQ-MNTCC")]
        public int MaxNameTableCharCount
        {
            get { return Binding.ReaderQuotas.MaxNameTableCharCount; }
            set { Binding.ReaderQuotas.MaxNameTableCharCount = value; }
        }

        [XmlAttribute("RQ-MSCL")]
        public int MaxStringContentLength
        {
            get { return Binding.ReaderQuotas.MaxStringContentLength; }
            set { Binding.ReaderQuotas.MaxStringContentLength = value; }
        }

        [XmlAttribute("RS-E")]
        public bool Enabled
        {
            get { return Binding.ReliableSession.Enabled; }
            set { Binding.ReliableSession.Enabled = value; }
        }

        [XmlAttribute("RS-IT")]
        public string InactivityTimeout
        {
            get { return Binding.ReliableSession.InactivityTimeout.ToString(); }
            set { Binding.ReliableSession.InactivityTimeout = TimeSpan.Parse(value); }
        }

        [XmlAttribute("RS-O")]
        public bool Ordered
        {
            get { return Binding.ReliableSession.Ordered; }
            set { Binding.ReliableSession.Ordered = value; }
        }

        [XmlAttribute("S-M")]
        public SecurityMode SecurityMode
        {
            get { return Binding.Security.Mode; }
            set { Binding.Security.Mode = value; }
        }

        [XmlAttribute("S-M-AS")]
        public string SecurityAlgorithmSuite
        {
            get { return Binding.Security.Message.AlgorithmSuite.GetType().Name; }
            set
            {
                switch (value)
                {
                    case "Basic256SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256;
                        break;

                    case "Basic192SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic192;
                        break;

                    case "Basic128SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128;
                        break;

                    case "TripleDesSecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDes;
                        break;

                    case "Basic256Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256Rsa15;
                        break;

                    case "Basic192Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic192Rsa15;
                        break;

                    case "Basic128Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Rsa15;
                        break;

                    case "TripleDesRsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesRsa15;
                        break;

                    case "Basic256Sha256SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256Sha256;
                        break;

                    case "Basic192Sha256SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic192Sha256;
                        break;

                    case "Basic128Sha256SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Sha256;
                        break;

                    case "TripleDesSha256SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesSha256;
                        break;

                    case "Basic256Sha256Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256Sha256Rsa15;
                        break;

                    case "Basic192Sha256Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic192Sha256Rsa15;
                        break;

                    case "Basic128Sha256Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Sha256Rsa15;
                        break;

                    case "TripleDesSha256Rsa15SecurityAlgorithmSuite":
                        Binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesSha256Rsa15;
                        break;
                }
            }
        }

        [XmlAttribute("S-M-ESC")]
        public bool EstablishSecurityContext
        {
            get { return Binding.Security.Message.EstablishSecurityContext; }
            set { Binding.Security.Message.EstablishSecurityContext = value; }
        }

        [XmlAttribute("S-M-CCT")]
        public MessageCredentialType MessageClientCredentialType
        {
            get { return Binding.Security.Message.ClientCredentialType; }
            set { Binding.Security.Message.ClientCredentialType = value; }
        }

        [XmlAttribute("S-M-NSC")]
        public bool NegotiateServiceCredential
        {
            get { return Binding.Security.Message.NegotiateServiceCredential; }
            set { Binding.Security.Message.NegotiateServiceCredential = value; }
        }

        [XmlAttribute("S-T-PCT")]
        public HttpProxyCredentialType ProxyCredentialType
        {
            get { return Binding.Security.Transport.ProxyCredentialType; }
            set { Binding.Security.Transport.ProxyCredentialType = value; }
        }

        [XmlAttribute("S-T-R")]
        public string Realm
        {
            get { return Binding.Security.Transport.Realm; }
            set { Binding.Security.Transport.Realm = value; }
        }

        [XmlAttribute("S-T-TCCT")]
        public HttpClientCredentialType TransportClientCredentialType
        {
            get { return Binding.Security.Transport.ClientCredentialType; }
            set { Binding.Security.Transport.ClientCredentialType = value; }
        }
    }
}
